/*
 * LEGO® MINDSTORMS EV3
 *
 * Copyright (C) 2010-2013 The LEGO Group
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

/*! \page debug Terminal Configuration
 *
 \verbatim


 TERMINAL CONFIGURATION (in top of "lms2012.h")

 Normal release:                     DEBUG not defined, TERMINAL_ENABLED = 0, DEBUG_UART = 4

 Printf working:                     DEBUG not defined, TERMINAL_ENABLED = 0, DEBUG_UART = 0

 Development with debug messages:    DEBUG defined, TERMINAL_ENABLED = 1, DEBUG_UART = 0

 */

//#define   DEBUG                         //!< When defined debug messages is output on standard I/O (d_uart is different)
#define   TERMINAL_ENABLED      0       //!< DEBUG terminal enabled (0 = disabled, 1 = enabled)#define   DEBUG_UART            4       //!< UART used for debug (0 = port1, 1 = port2, ... 4 = none)
/*    \endverbatim */

//#define   DEBUG_VM
//#define   DEBUG_TRACE_TASK
//#define   DEBUG_C_COM
//#define   DEBUG_C_INPUT
//#define   DEBUG_C_INPUT_DAISYCHAIN
//#define   DEBUG_C_INPUT_DATALOG
//#define   DEBUG_C_INPUT_FAST_DATALOG
//#define   DEBUG_C_MEMORY
//#define   DEBUG_C_MEMORY_LOG
//#define   DEBUG_C_MEMORY_FILE
//#define   DEBUG_C_MEMORY_LOW
//#define   DEBUG_C_SOUND
//#define   DEBUG_C_UI
//#define   DEBUG_D_ANALOG
//#define   DEBUG_D_POWER
//#define   DEBUG_D_UART
//#define   DEBUG_D_UART_ERROR
//#define   DEBUG_D_UI
//#define   DEBUG_D_SOUND
//#define   DEBUG_D_IIC
//#define   DEBUG_D_USBDEV
//#define   ENABLE_TEST_ON_PORT4
//#define   BUFPRINTSIZE 100000
//#define   REMEMBER_TO_ENABLE_SAVE_USER_DATA
//#define   REMEMBER_TO_FIX_TYPEDATA
//#define   DEBUG_TRACE_USB_COMMAND
//#define   DEBUG_TRACE_MODE_CHANGE
//#define   DEBUG_TRACE_KEY
//#define   DEBUG_TRACE_ANGLE
//#define   DEBUG_TRACE_US
//#define   DEBUG_TRACE_VM
//#define   DEBUG_TRACE_DAISYCHAIN
//#define   DEBUG_BYTECODE_TIME
//#define   DEBUG_TRACE_FREEZE
//#define   DEBUG_TRACE_FILENAME
//#define   DEBUG_SDCARD
//#define   DEBUG_USBSTICK
//#define   DEBUG_VIRTUAL_BATT_TEMP
//#define   DEBUG_TEMP_SHUTDOWN
//#define   DEBUG_BACK_BLOCKED
#define   DEBUG_RECHARGEABLE

#ifndef   LMS2012_H_
#define   LMS2012_H_

//  HARDWARE PLATFORM

#define   EP2                   4       //!< Schematics revision D#define   FINALB                3       //!< Schematics revision B and C#define   FINAL                 2       //!< Final prototype#define   SIMULATION            0       //!< LEGO digital simulation
#define   PLATFORM_START        FINAL   //!< Oldest supported hardware (older versions will use this)#define   PLATFORM_END          EP2     //!< Newest supported hardware (newer versions will use this)
// Will be removed when not used anymore
#define   A4                    -1
#define   EVALBOARD             -2
#define   ONE2ONE               1       //!< First real size prototype
#ifdef LEGO_SIMULATION
#define HARDWARE SIMULATION
#else

#ifndef   HARDWARE
#define HARDWARE      FINAL           //!< Actual hardware platform (must be one of above)#endif

#endif

//  Support for module parameter "HwId"
//
//  Readout   File    int       PCB
//
//  V1.00     10      10        MP      (h = home, e = education)
//  V0.50     05      5         EP3
//  V0.40     04      4         EP2
//  V0.30     03      3         EP1     (FINALB)  (DEFAULT if file "HwId" not found)
//  V0.20     02      2         FINAL

#ifdef HW_ID_SUPPORT

char *HwId = "03";

#define   HWID          (((HwId[0] - '0') * 10) + (HwId[1] - '0'))

#endif

//  FIRMWARE VARIANTS

//#define   OLDCALL                       //!< Don't use optimised sub calls
//#define   DISABLE_PRU_UARTS             //!< Don't use port 3 and 4 for UART sensors
//#define   DISABLE_OLD_COLOR             //!< Don't support NXT color sensor
//#define   DISABLE_ADC                   //!< Don't use ADC (no clock EMC test)
//#define   ADC_BITBANGING                //!< Don't use SPI for a/d converter
//#define   DISABLE_DAISYCHAIN
//#define   DISABLE_DAISYCHAIN_COM_CALL
//#define   DISABLE_FAST_DATALOG_BUFFER
//#define   DISABLE_BUMBED
//#define   LOG_ASCII
//#define   DISABLE_FIQ_IIC
#define   UART1_FAKE_INTERRUPT          //!< Don't use real interrupt on UART1 (linux prompt)//#define   DISABLE_LOW_VOLTAGE           //!< Don't shut down on low voltage
//#define   ENABLE_HIGH_CURRENT           //!< Don't shut down on high current
//#define   DISABLE_LOW_MEMORY            //!< Don't check low memory
//#define   DISABLE_UART_DATA_ERROR       //!< Don't reset UART sensor if timeout or crc error
#define   DISABLE_PREEMPTED_VM          //!< Don't run VM as preempted//#define   DISABLE_SDCARD_SUPPORT        //!< Don't use SD card
#define   DISABLE_USBSTICK_SUPPORT      //!< Don't use USB stick//#define   ENABLE_PERFORMANCE_TEST       //!< Show performance bar in the top line
//#define   ENABLE_LOAD_TEST              //!< Show integrated current in the top line
//#define   ENABLE_MEMORY_TEST            //!< Show used memory in the top line
//#define   ENABLE_STATUS_TEST
//#define   DISABLE_VIRTUAL_BATT_TEMP
//#define   DISABLE_SOUND
//#define   DISABLE_PAR_ALIGNMENT         //!< Disable possibility to align sub call parameter types
//#define   DISABLE_NEW_CALL_MUTEX        //!< Disable smart object switching after return from non reentrant sub call (enables blocked thread call)
//#define   DISABLE_SYSTEM_BYTECODE       //!< Disable the use of opSYSTEM command
//#define   DISABLE_FILENAME_CHECK        //!< Disable "c_memory" filename check
//#define   DISABLE_AD_WORD_PROTECT       //!< Disable A/D word result protection

#define   TESTDEVICE    3

#ifdef Linux_X86
#define   DISABLE_DAISYCHAIN
#define   DISABLE_DAISYCHAIN_COM_CALL
#endif

#ifndef PCASM
#include  <asm/types.h>
#endif

#include  "lmstypes.h"
#include  "bytecodes.h"

// Hardware

#define   OUTPUTS                       vmOUTPUTS                     //!< Number of output ports in the system#define   INPUTS                        vmINPUTS                      //!< Number of input  ports in the system#define   BUTTONS                       vmBUTTONS                     //!< Number of buttons in the system#define   LEDS                          vmLEDS                        //!< Number of LEDs in the system
#define   LCD_WIDTH                     vmLCD_WIDTH                   //!< LCD horizontal pixels#define   LCD_HEIGHT                    vmLCD_HEIGHT                  //!< LCD vertical pixels#define   TOPLINE_HEIGHT                vmTOPLINE_HEIGHT              //!< Top line vertical pixels#define   LCD_STORE_LEVELS              vmLCD_STORE_LEVELS            //!< Store levels
// Software

#define   FG_COLOR                      vmFG_COLOR                    //!<  Foreground color#define   BG_COLOR                      vmBG_COLOR                    //!<  Background color
#define   CHAIN_DEPT                    vmCHAIN_DEPT                  //!< Number of bricks in the USB daisy chain (master + slaves)
#define   EVENT_BT_PIN                  vmEVENT_BT_PIN

// Folders

#define   MEMORY_FOLDER                 vmMEMORY_FOLDER
#define   PROGRAM_FOLDER                vmPROGRAM_FOLDER
#define   DATALOG_FOLDER                vmDATALOG_FOLDER
#define   SDCARD_FOLDER                 vmSDCARD_FOLDER
#define   USBSTICK_FOLDER               vmUSBSTICK_FOLDER

// Files
#define   DETAILS_FILE                  vmDETAILS_FILE                //!< File containing firmware version
// Extensions

#define   EXT_SOUND                     vmEXT_SOUND                   //!< Rudolf sound file#define   EXT_GRAPHICS                  vmEXT_GRAPHICS                //!< Rudolf graphics file#define   EXT_BYTECODE                  vmEXT_BYTECODE                //!< Rudolf byte code file#define   EXT_TEXT                      vmEXT_TEXT                    //!< Rudolf text file#define   EXT_DATALOG                   vmEXT_DATALOG                 //!< Rudolf datalog file#define   EXT_PROGRAM                   vmEXT_PROGRAM                 //!< Rudolf program byte code file#define   EXT_CONFIG                    vmEXT_CONFIG                  //!< rudolf configuration file
/*! \page system
 *
 *  \verbatim
 */

#define   PROJECT                       "LMS2012"
#define   VERS                          1.04
#define   SPECIALVERS                   'H'           //!< Minor version (not shown if less than ASCII zero)
#define   MAX_PROGRAMS          SLOTS                 //!< Max number of programs (including UI and direct commands) running at a time#define   MAX_BREAKPOINTS       4                     //!< Max number of breakpoints (opCODES depends on this value)#define   MAX_LABELS            32                    //!< Max number of labels per program#define   MAX_DEVICE_TYPE       127                   //!< Highest type number (positive)#define   MAX_VALID_TYPE        vmMAX_VALID_TYPE      //!< Highest valid type#define   MAX_DEVICE_MODES      8                     //!< Max number of modes in one device#define   MAX_DEVICE_DATASETS   8                     //!< Max number of data sets in one device#define   MAX_DEVICE_DATALENGTH 32                    //!< Max device data length
#define   MAX_DEVICE_BUSY_TIME  1200                  //!< Max number of mS a device can be busy when read
#define   MAX_DEVICE_TYPES      ((MAX_DEVICE_TYPE + 1) * MAX_DEVICE_MODES)//!< Max number of different device types and modes (max type data list size)
#define   MAX_FRAMES_PER_SEC    10                    //!< Max frames per second update in display
#define   CACHE_DEEPT           10                    //!< Max number of programs cached (in RECENT FILES MENU)#define   MAX_HANDLES           250                   //!< Max number of handles to memory pools and arrays in one program
#define   MAX_ARRAY_SIZE        1000000000            //!< Max array size#define   MIN_ARRAY_ELEMENTS    0                     //!< Min elements in a DATA8 array
#define   INSTALLED_MEMORY      6000                  //!< Flash allocated to hold user programs/data#define   RESERVED_MEMORY       100                   //!< Memory reserve for system [KB]#define   LOW_MEMORY            500                   //!< Low memory warning [KB]
#define   LOGBUFFER_SIZE        1000                  //!< Min log buffer size#define   DEVICE_LOGBUF_SIZE    300                   //!< Device log buffer size (black layer buffer)#define   MIN_LIVE_UPDATE_TIME  10                    //!< [mS] Min sample time when live update
#define   MIN_IIC_REPEAT_TIME   10                    //!< [mS] Min IIC device repeat time#define   MAX_IIC_REPEAT_TIME   1000                  //!< [mS] Max IIC device repeat time
#define   MAX_COMMAND_BYTECODES 64                    //!< Max number of byte codes in a debug terminal direct command#define   MAX_COMMAND_LOCALS    64                    //!< Max number of bytes allocated for direct command local variables#define   MAX_COMMAND_GLOBALS   1021                  //!< Max number of bytes allocated for direct command global variables
#define   UI_PRIORITY           20                    //!< UI byte codes before switching VM thread#define   C_PRIORITY            200                   //!< C call byte codes
#ifndef DISABLE_PREEMPTED_VM
#define   PRG_PRIORITY          2000                  //!< Prg byte codes before switching VM thread#else
#define   PRG_PRIORITY          200                   //!< Prg byte codes before switching VM thread#endif

#define   BUTTON_DEBOUNCE_TIME        30
#define   BUTTON_START_REPEAT_TIME    400
#define   BUTTON_REPEAT_TIME          200

#define   LONG_PRESS_TIME       3000                  //!< [mS] Time pressed before long press recognised
#define   ADC_REF               5000                  //!< [mV]  maximal value on ADC#define   ADC_RES               4095                  //!< [CNT] maximal count on ADC
#define   IN1_ID_HYSTERESIS     50                    //!< [mV]  half of the span one Id takes up on input connection 1 voltage#define   OUT5_ID_HYSTERESIS    100                   //!< [mV]  half of the span one Id takes up on output connection 5 voltage
#define   DEVICE_UPDATE_TIME    1000000               //!< Min device (sensor) update time [nS]#define   DELAY_TO_TYPEDATA     10000                 //!< Time from daisy chain active to upload type data [mS]#define   DAISYCHAIN_MODE_TIME  10                    //!< Time for daisy chain change mode [mS]#define   MAX_FILE_HANDLES      64                    //!< Max number of down load file handles#define   MIN_HANDLE            3                     //!< Min file handle to close
#define   ID_LENGTH             7                     //!< Id length  (BT MAC id) (incl. zero terminator)#define   NAME_LENGTH           12                    //!< Name length (not including zero termination)
#define   ERROR_BUFFER_SIZE     8                     //!< Number of errors in buffer
#define   PWM_DEVICE            "lms_pwm"             //!< PWM device name#define   PWM_DEVICE_NAME       "/dev/lms_pwm"        //!< PWM device file name
#define   MOTOR_DEVICE          "lms_motor"           //!< TACHO device name#define   MOTOR_DEVICE_NAME     "/dev/lms_motor"      //!< TACHO device file name
#define   ANALOG_DEVICE         "lms_analog"          //!< ANALOG device name#define   ANALOG_DEVICE_NAME    "/dev/lms_analog"     //!< ANALOG device file name
#define   POWER_DEVICE          "lms_power"           //!< POWER device name#define   POWER_DEVICE_NAME     "/dev/lms_power"      //!< POWER device file name
#define   DCM_DEVICE            "lms_dcm"             //!< DCM device name#define   DCM_DEVICE_NAME       "/dev/lms_dcm"        //!< DCM device file name
#define   UI_DEVICE             "lms_ui"              //!< UI device name#define   UI_DEVICE_NAME        "/dev/lms_ui"         //!< UI device file name
#define   LCD_DEVICE            "lms_display"         //!< DISPLAY device name//#define   LCD_DEVICE_NAME       "/dev/lms_display"    //!< DISPLAY device file name
#define   LCD_DEVICE_NAME       "/dev/fb0"            //!< DISPLAY device file name
#define   UART_DEVICE           "lms_uart"            //!< UART device name#define   UART_DEVICE_NAME      "/dev/lms_uart"       //!< UART device file name
#define   USBDEV_DEVICE         "lms_usbdev"          //!< USB device#define   USBDEV_DEVICE_NAME    "/dev/lms_usbdev"     //!< USB device
#define   USBHOST_DEVICE        "lms_usbhost"         //!< USB host#define   USBHOST_DEVICE_NAME   "/dev/lms_usbhost"    //!< USB host
#define   SOUND_DEVICE          "lms_sound"           //!< SOUND device name#define   SOUND_DEVICE_NAME     "/dev/lms_sound"      //!< SOUND device
#define   IIC_DEVICE            "lms_iic"             //!< IIC device name#define   IIC_DEVICE_NAME       "/dev/lms_iic"        //!< IIC device
#define   BT_DEVICE             "lms_bt"              //!< BT device name#define   BT_DEVICE_NAME        "/dev/lms_bt"         //!< BT device
#define   UPDATE_DEVICE          "lms_update"         //!< UPDATE device name#define   UPDATE_DEVICE_NAME     "/dev/lms_update"    //!< UPDATE device
#define   TEST_PIN_DEVICE       "lms_tst_pin"         //!< TEST pin device name#define   TEST_PIN_DEVICE_NAME  "/dev/lms_tst_pin"    //!< TEST pin device file name
#define   TEST_UART_DEVICE      "lms_tst_uart"        //!< TEST UART device name#define   TEST_UART_DEVICE_NAME "/dev/lms_tst_uart"   //!< TEST UART device file name
#define   DIR_DEEPT             vmDIR_DEEPT           //!< Max directory items allocated
// File

//***********************************************************************************************************************
//! \todo Filename sizes should only use vmPATHSIZE, vmNAMESIZE, vmEXTSIZE and vmFILENAMESIZE

#define   FILENAMESIZE          vmFILENAMESIZE        //!< All inclusive (path, filename, extension and zero termination)#define   FILENAME_SIZE         52                    //!< User filename size without extension including zero#define   FOLDERNAME_SIZE       10                    //!< Folder name size relative to "lms2012" folder including zero#define   SUBFOLDERNAME_SIZE    FILENAME_SIZE         //!< Sub folder name size without "/" including zero
#define   MAX_FILENAME_SIZE     (FOLDERNAME_SIZE + SUBFOLDERNAME_SIZE + FILENAME_SIZE + 5)

//***********************************************************************************************************************

#define   TYPEDATE_FILE_NAME    "typedata"            //!< TypeData filename#define   ICON_FILE_NAME        "icon"                //!< Icon image filename#define   TEXT_FILE_NAME        "text"                //!< Text filename
#define   DEMO_FILE_NAME        "../prjs/BrkProg_SAVE/Demo.rpf"

// Memory

// SD card

#ifdef Linux_X86
#define   SDCARD_DEVICE1        "/dev/mmcblk0"
#define   SDCARD_DEVICE2        "/dev/mmcblk0p1"
#else
#define   SDCARD_DEVICE1        "/dev/mmcblk0"
#define   SDCARD_DEVICE2        "/dev/mmcblk0p1"
#endif

#define   SDCARD_MOUNT          "./mount_sdcard"
#define   SDCARD_UNMOUNT        "./unmount_sdcard"

// USB stick

#ifndef Linux_X86
#define   USBSTICK_DEVICE       "/dev/sda"
#else
#define   USBSTICK_DEVICE       "/dev/sdf1"
#endif

#define   USBSTICK_MOUNT        "./mount_usbstick"
#define   USBSTICK_UNMOUNT      "./unmount_usbstick"

/*
 #define   DEFAULT_PRJS_FOLDER   "~/lms2012/prjs"      //!< Project folder name without trailing "/"
 #define   DEFAULT_APPS_FOLDER   "~/lms2012/apps"      //!< Applet folder name without trailing "/"
 #define   DEFAULT_TOOLS_FOLDER  "~/lms2012/tools"     //!< Setting folder name without trailing "/"
 #define   DEFAULT_SYS_FOLDER    "~/lms2012/sys"       //!< System folder name without trailing "/"
 #define   DEFAULT_SETUP_FOLDER  "~/lms2012/sys"       //!< Setup folder name without trailing "/"
 #define   DEFAULT_SD_FOLDER     "~/lms2012/SD Card"   //!< Sd card folder name without trailing "/"
 #define   DEFAULT_USB_FOLDER    "~/lms2012/USB Memory"//!< USB Memory folder name without trailing "/"
 */

#define   DEFAULT_FOLDER        "ui"                  //!< Folder containing the first small programs#define   DEFAULT_UI            "ui"                  //!< Default user interface
#define   DEFAULT_VOLUME        vmDEFAULT_VOLUME
#define   DEFAULT_SLEEPMINUTES  vmDEFAULT_SLEEPMINUTES

#define   COM_CMD_DEVICE_NAME   USBDEV_DEVICE_NAME    //!< USB HID command pipe device file name
/*! \endverbatim
 *
 */

/*! \page powermanagement Power Management
 *
 *  This section describes various constants used in the power management
 *
 *
 *\n
 *  <hr size="1"/>
 *  <b>Battery Indicator</b>
 *\n
 *  <hr size="1"/>
 *  \verbatim
 */

#define   BATT_INDICATOR_HIGH           7500          //!< Battery indicator high [mV]#define   BATT_INDICATOR_LOW            6200          //!< Battery indicator low [mV]
#define   ACCU_INDICATOR_HIGH           7500          //!< Rechargeable battery indicator high [mV]#define   ACCU_INDICATOR_LOW            7100          //!< Rechargeable battery indicator low [mV]
/*! \endverbatim
 *  \subpage pmbattind
 *\n
 *  <hr size="1"/>
 *  <b>Low Voltage Shutdown</b>
 *\n
 *  <hr size="1"/>
 *  \verbatim
 */

#define   LOW_VOLTAGE_SHUTDOWN_TIME     10000         //!< Time from shutdown lower limit to shutdown [mS]
#define   BATT_WARNING_HIGH             6.2           //!< Battery voltage warning upper limit [V]#define   BATT_WARNING_LOW              5.5           //!< Battery voltage warning lower limit [V]#define   BATT_SHUTDOWN_HIGH            5.5           //!< Battery voltage shutdown upper limit [V]#define   BATT_SHUTDOWN_LOW             4.5           //!< Battery voltage shutdown lower limit [V]
#define   ACCU_WARNING_HIGH             7.1           //!< Rechargeable battery voltage warning upper limit [V]#define   ACCU_WARNING_LOW              6.5           //!< Rechargeable battery voltage warning lower limit [V]#define   ACCU_SHUTDOWN_HIGH            6.5           //!< Rechargeable battery voltage shutdown upper limit [V]#define   ACCU_SHUTDOWN_LOW             6.0           //!< Rechargeable battery voltage shutdown lower limit [V]
/*! \endverbatim
 *  \subpage pmbattsd
 *\n
 */
#ifdef ENABLE_HIGH_CURRENT
/*! \page powermanagement
 *
 *  <hr size="1"/>
 *  <b>High Load Shutdown</b>
 *\n
 *  <hr size="1"/>
 *  \verbatim
 */

#define   LOAD_SHUTDOWN_FAIL            4.0           //!< Current limit for instantly shutdown [A]#define   LOAD_SHUTDOWN_HIGH            3.0           //!< Current limit for integrated current shutdown [A*S]#define   LOAD_BREAK_EVEN               1.75          //!< Current limit for integrated current break even [A*S]
#define   LOAD_SLOPE_UP                 0.2           //!< Current slope when current is above break even [A/S]#define   LOAD_SLOPE_DOWN               0.1           //!< Current slope when current is below break even [A/S]
/*! \endverbatim
 *  \subpage pmloadsd
 *\n
 */
#endif

#ifndef DISABLE_VIRTUAL_BATT_TEMP
/*! \page powermanagement
 *
 *  <hr size="1"/>
 *  <b>High Temperature Shutdown</b>
 *\n
 *  <hr size="1"/>
 *  \verbatim
 */

#define   TEMP_SHUTDOWN_FAIL            45.0          //!< Temperature rise before fail shutdown  [C]#define   TEMP_SHUTDOWN_WARNING         40.0          //!< Temperature rise before warning        [C]
/*! \endverbatim
 *  \subpage pmtempsd
 *\n
 */
#endif

#define   UPDATE_TIME1          2                     //!< Update repeat time1  [mS]#define   UPDATE_TIME2          10                    //!< Update repeat time2  [mS]#define   UPDATE_MEMORY         200                   //!< Update memory size   [mS]#define   UPDATE_SDCARD         500                   //!< Update sdcard size   [mS]#define   UPDATE_USBSTICK       500                   //!< Update usbstick size [mS]
// Per start of (polution) defines
#define   MAX_SOUND_DATA_SIZE   250
#define   SOUND_CHUNK           250
#define SOUND_ADPCM_CHUNK       125
#define SOUND_MASTER_CLOCK  132000000
#define SOUND_TONE_MASTER_CLOCK 1031250
#define SOUND_MIN_FRQ       250
#define SOUND_MAX_FRQ       10000
#define SOUND_MAX_LEVEL     8
#define SOUND_FILE_BUFFER_SIZE  SOUND_CHUNK + 2 // 12.8 mS @ 8KHz#define SOUND_BUFFER_COUNT  3
#define SOUND_FILE_FORMAT_NORMAL    0x0100  // RSO-file#define SOUND_FILE_FORMAT_COMPRESSED  0x0101  // RSO-file compressed// Per end of defines

/*!
 *
 * \n
 */

#define   VtoC(V)               ((UWORD)((V * ADC_RES) / ADC_REF))
#define   CtoV(C)               ((UWORD)((C * ADC_REF) / ADC_RES))
#define   MtoV(M)               ((UWORD)((M * ADC_REF * 100) / (ADC_RES * 52)))

#define   KB                    1024

// Reserved device types
typedef enum {
//  TYPE_KEEP                     =   0,  //!< Type value that won't change type in byte codes
	TYPE_NXT_TOUCH = 1,  //!< Device is NXT touch sensor
	TYPE_NXT_LIGHT = 2,  //!< Device is NXT light sensor
	TYPE_NXT_SOUND = 3,  //!< Device is NXT sound sensor
	TYPE_NXT_COLOR = 4,  //!< Device is NXT color sensor

	TYPE_TACHO = 7,  //!< Device is a tacho motor
	TYPE_MINITACHO = 8,  //!< Device is a mini tacho motor
	TYPE_NEWTACHO = 9,  //!< Device is a new tacho motor

	TYPE_THIRD_PARTY_START = 50,
	TYPE_THIRD_PARTY_END = 99,

	TYPE_IIC_UNKNOWN = 100,

	TYPE_NXT_TEST = 101,  //!< Device is a NXT ADC test sensor

	TYPE_NXT_IIC = 123,  //!< Device is NXT IIC sensor
	TYPE_TERMINAL = 124,  //!< Port is connected to a terminal
	TYPE_UNKNOWN = 125,  //!< Port not empty but type has not been determined
	TYPE_NONE = 126,  //!< Port empty or not available
	TYPE_ERROR = 127,  //!< Port not empty and type is invalid
} TYPE;

/*! \page connections Connections
 *
 *  \anchor connectiontypes
 *
 *  Following defines sets the input and output port connection type\n
 *
 *  These connection types are evaluated in the DCM driver \ref DcmDriver "Device Detection Manager Driver"
 *
 *  \verbatim
 */

typedef enum {
	CONN_UNKNOWN = 111,  //!< Connection is fake (test)

	CONN_DAISYCHAIN = 117,  //!< Connection is daisy chained
	CONN_NXT_COLOR = 118,  //!< Connection type is NXT color sensor
	CONN_NXT_DUMB = 119,  //!< Connection type is NXT analog sensor
	CONN_NXT_IIC = 120,  //!< Connection type is NXT IIC sensor

	CONN_INPUT_DUMB = 121, //!< Connection type is LMS2012 input device with ID resistor
	CONN_INPUT_UART = 122,  //!< Connection type is LMS2012 UART sensor

	CONN_OUTPUT_DUMB = 123, //!< Connection type is LMS2012 output device with ID resistor
	CONN_OUTPUT_INTELLIGENT = 124, //!< Connection type is LMS2012 output device with communication
	CONN_OUTPUT_TACHO = 125, //!< Connection type is LMS2012 tacho motor with series ID resistance

	CONN_NONE = 126,  //!< Port empty or not available
	CONN_ERROR = 127,  //!< Port not empty and type is invalid
} CONN;

/*\endverbatim
 *
 *  \n
 */

/*! \page objectstatus Object Status
 *
 \verbatim

 Image load  ->   Initialize all objects


 Initialize  ->   if TriggerCount == 0 ->  RUNNING   (VMTHREAD)
 else                 ->  STOPPED   (waiting for 1. trigger)

 1.Trigger   ->   Initialise           ->  WAITING

 Triggered   ->   Enqueue              ->  RUNNING

 Done        ->   Dequeue              ->  STOPPED


 Program start
 |
 v
 STOPPED -------> WAITING -------> RUNNING --------,
 ^    1.trig/          n.trig/          done/   |
 |                     Reset+Enqueue    Dequeue |
 |                                              |
 '----------------------------------------------'

 \endverbatim
 */

/*! \enum DSPSTAT
 *
 *        Dispatch status values
 */
typedef enum {
	NOBREAK = 0x0100,               //!< Dispatcher running (looping)
	STOPBREAK = 0x0200,               //!< Break because of program stop
	SLEEPBREAK = 0x0400,               //!< Break because of sleeping
	INSTRBREAK = 0x0800,               //!< Break because of opcode break
	BUSYBREAK = 0x1000,             //!< Break because of waiting for completion
	PRGBREAK = 0x2000,               //!< Break because of program break
	USERBREAK = 0x4000,               //!< Break because of user decision
	FAILBREAK = 0x8000                //!< Break because of fail
} DSPSTAT;

typedef void (*PRIM)(void);      //!< Prototype for all byte codes

/*! \page memorylayout Memory Layout
 *
 *  RAM layout
 *
 *-   GlobalVariables                   (aligned)
 *
 *-   ObjectPointerList                 (aligned)
 *
 *-   OBJ                               (aligned)
 *  -   Ip                              (4 bytes)
 *  -   Status                          (2 bytes)
 *  -   TriggerCount/CallerId           (2 bytes)
 *  -   Local                           (0..MAX Bytes)\n
 *
 */

/*! \struct OBJ
 *          Object data is used to hold the variables used for an object (allocated at image load time)
 */
typedef struct                        // Object
{
	IP Ip;                           //!< Object instruction pointer
	LP pLocal;                       //!< Local variable pointer
#ifndef DISABLE_NEW_CALL_MUTEX
	UBYTE ObjStatus;                    //!< Object status
	UBYTE Blocked;
#else
	UWORD ObjStatus;                    //!< Object status
#endif
	union                         //!< Different meaning for SUBCALL and BLOCKS
	{
		OBJID CallerId; //!< Caller id used for SUBCALL to save object id to return to
		TRIGGER TriggerCount;   //!< Trigger count used by BLOCK's trigger logic
	} u;
	VARDATA Local[];                 //!< Poll of bytes used for local variables
} OBJ;

/*! \struct BRKP
 *          Breakpoint data hold information used for breakpoint
 */
typedef struct {
	IMINDEX Addr;             //!< Offset to breakpoint address from image start
	OP OpCode;                       //!< Saved substituted opcode
} BRKP;

/*! \struct PRG
 *          Program data hold information about a program
 */
typedef struct {
	ULONG InstrCnt;       //!< Instruction counter used for performance analyses
	ULONG InstrTime;         //!< Instruction time used for performance analyses

	ULONG StartTime;                  //!< Program start time [mS]
	ULONG RunTime;                    //!< Program run time [uS]

	IP pImage;                     //!< Pointer to start of image
	GP pData;                      //!< Pointer to start of data
	GP pGlobal;                    //!< Pointer to start of global bytes
	OBJHEAD* pObjHead;                   //!< Pointer to start of object headers
	OBJ** pObjList;                   //!< Pointer to object pointer list
	IP ObjectIp;                   //!< Working object Ip
	LP ObjectLocal;                //!< Working object locals

	OBJID Objects;                    //!< No of objects in image
	OBJID ObjectId;                   //!< Active object id

	OBJSTAT Status;                     //!< Program status
	OBJSTAT StatusChange;               //!< Program status change
	RESULT Result;                     //!< Program result (OK, BUSY, FAIL)

	BRKP Brkp[MAX_BREAKPOINTS];      //!< Storage for breakpoint logic

	LABEL Label[MAX_LABELS];          //!< Storage for labels
	UWORD Debug;                      //!< Debug flag

	DATA8 Name[FILENAME_SIZE];

} PRG;

#define     TYPE_NAME_LENGTH    11
#define     SYMBOL_LENGTH       4       //!< Symbol leng th (not including zero)
/*! \struct TYPES
 *          Device type data
 */
typedef struct // if data type changes - remember to change "cInputTypeDataInit" !
{
	SBYTE Name[TYPE_NAME_LENGTH + 1]; //!< Device name
	DATA8 Type;                       //!< Device type
	DATA8 Connection;
	DATA8 Mode;                       //!< Device mode
	DATA8 DataSets;
	DATA8 Format;
	DATA8 Figures;
	DATA8 Decimals;
	DATA8 Views;
	DATAF RawMin;                     //!< Raw minimum value      (e.c. 0.0)
	DATAF RawMax;                     //!< Raw maximum value      (e.c. 1023.0)
	DATAF PctMin;                     //!< Percent minimum value  (e.c. -100.0)
	DATAF PctMax;                     //!< Percent maximum value  (e.c. 100.0)
	DATAF SiMin;                      //!< SI unit minimum value  (e.c. -100.0)
	DATAF SiMax;                      //!< SI unit maximum value  (e.c. 100.0)
	UWORD InvalidTime;                //!< mS from type change to valid data
	UWORD IdValue;                   //!< Device id value        (e.c. 0 ~ UART)
	DATA8 Pins;                       //!< Device pin setup
	SBYTE Symbol[SYMBOL_LENGTH + 1];  //!< SI unit symbol
	UWORD Align;
} TYPES;

#define     TYPE_PARAMETERS         19  //!< Number of members in the structure above#define     MAX_DEVICE_INFOLENGTH   54  //!< Number of bytes in the structure above (can not be changed)
/*!\enum  ERR
 *
 *        Describes error numbers
 */
typedef enum {
	TOO_MANY_ERRORS_TO_BUFFER,
	TYPEDATA_TABEL_FULL,
	TYPEDATA_FILE_NOT_FOUND,
	ANALOG_DEVICE_FILE_NOT_FOUND,
	ANALOG_SHARED_MEMORY,
	UART_DEVICE_FILE_NOT_FOUND,
	UART_SHARED_MEMORY,
	IIC_DEVICE_FILE_NOT_FOUND,
	IIC_SHARED_MEMORY,
	DISPLAY_SHARED_MEMORY,
	UI_SHARED_MEMORY,
	UI_DEVICE_FILE_NOT_FOUND,
	LCD_DEVICE_FILE_NOT_FOUND,
	OUTPUT_SHARED_MEMORY,
	COM_COULD_NOT_OPEN_FILE,
	COM_NAME_TOO_SHORT,
	COM_NAME_TOO_LONG,
	COM_INTERNAL,
	VM_INTERNAL,
	VM_PROGRAM_VALIDATION,
	VM_PROGRAM_NOT_STARTED,
	VM_PROGRAM_FAIL_BREAK,
	VM_PROGRAM_INSTRUCTION_BREAK,
	VM_PROGRAM_NOT_FOUND,
	SOUND_DEVICE_FILE_NOT_FOUND,
	SOUND_SHARED_MEMORY,
	FILE_OPEN_ERROR,
	FILE_READ_ERROR,
	FILE_WRITE_ERROR,
	FILE_CLOSE_ERROR,
	FILE_GET_HANDLE_ERROR,
	FILE_NAME_ERROR,
	USB_SHARED_MEMORY,
	OUT_OF_MEMORY,
	ERRORS
} ERR;

//        INTERFACE FOR SHARED LIBRARIES

extern void PrimParAdvance(void);                    // Dummy get parameter

extern void* PrimParPointer(void); // Get pointer to primitives and system calls parameters

extern IP GetImageStart(void);                  // Get pointer to start of image

extern void SetDispatchStatus(DSPSTAT Status); // Set dispatch status (result from executing byte code)

extern void SetInstructions(ULONG Instructions); // Set number of instructions before VMThread change

extern PRGID CurrentProgramId(void);                  // Get current program id

extern OBJSTAT ProgramStatus(PRGID PrgId);              // Get program status

extern OBJSTAT ProgramStatusChange(PRGID PrgId);    // Get program status change

extern void ProgramEnd(PRGID PrgId);

extern OBJID CallingObjectId(void);                   // Get calling objects id

extern void AdjustObjectIp(IMOFFS Value);            // Adjust IP

extern IP GetObjectIp(void);                       // Get IP

extern void SetObjectIp(IP Ip);                      // Set IP

extern ULONG GetTimeUS(void);                         // Get uS

extern ULONG GetTimeMS(void);                         // Get mS

extern ULONG GetTime(void);                           // Get actual program time

extern ULONG CurrentObjectIp(void);                   // Get current object ip

extern void VmPrint(char *pString);                  // print string

extern void SetTerminalEnable(DATA8 Value);          // Terminal enable/disable

extern DATA8 GetTerminalEnable(void);               // Get terminal enable state

extern void GetResourcePath(char *pString, DATA8 MaxLength); // Get resource path

extern void* VmMemoryResize(HANDLER Handle, DATA32 Elements);

extern void SetVolumePercent(DATA8 Volume);

extern DATA8 GetVolumePercent(void);

extern void SetSleepMinutes(DATA8 Minutes);

extern DATA8 GetSleepMinutes(void);

extern DSPSTAT ExecuteByteCode(IP pByteCode, GP pGlobals, LP pLocals); // Execute byte code stream (C-call)

extern DATA8 CheckSdcard(DATA8 *pChanged, DATA32 *pTotal, DATA32 *pFree,
		DATA8 Force);

extern DATA8 CheckUsbstick(DATA8 *pChanged, DATA32 *pTotal, DATA32 *pFree,
		DATA8 Force);

extern void SetUiUpdate(void);

extern RESULT ValidateChar(DATA8 *pChar, DATA8 Set);

extern RESULT ValidateString(DATA8 *pString, DATA8 Set);

extern ERR LogErrorGet(void);

#ifdef BUFPRINTSIZE
extern void BufPrint(char Cmd,char *pFormat, ...);
#endif

#define   ERR_STRING_SIZE         vmERR_STRING_SIZE          // Inclusive zero termination
extern void LogErrorNumber(ERR Error);               // Log error number
extern DATA8 LogErrorNumberExists(ERR Error);

#ifndef   DISABLE_OLD_COLOR

#define   COLORS                        4
#define   CALPOINTS                     3

/*! \page NxtColorMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *
 *  \verbatim
 */

typedef struct {
	ULONG Calibration[CALPOINTS][COLORS];
	UWORD CalLimits[CALPOINTS - 1];
	UWORD Crc;
	UWORD ADRaw[COLORS];
	UWORD SensorRaw[COLORS];
} COLORSTRUCT;

/*\endverbatim
 *
 *  \n
 */

#endif

//        INTERFACE BETWEEN SHARED LIBRARIES AND MODULES

/*! \page AnalogModuleMemory
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the raw analogue values for use in userspace
 *  this pointer will point to a struct and the layout is following:
 *
 *  \verbatim
 */

typedef struct {
	DATA16 InPin1[INPUTS];         //!< Analog value at input port connection 1
	DATA16 InPin6[INPUTS];         //!< Analog value at input port connection 6
	DATA16 OutPin5[OUTPUTS];       //!< Analog value at output port connection 5
	DATA16 BatteryTemp;            //!< Battery temperature
	DATA16 MotorCurrent;           //!< Current flowing to motors
	DATA16 BatteryCurrent;         //!< Current flowing from the battery
	DATA16 Cell123456;          //!< Voltage at battery cell 1, 2, 3,4, 5, and 6
#ifndef DISABLE_FAST_DATALOG_BUFFER
	DATA16 Pin1[INPUTS][DEVICE_LOGBUF_SIZE];   //!< Raw value from analog device
	DATA16 Pin6[INPUTS][DEVICE_LOGBUF_SIZE];   //!< Raw value from analog device
	UWORD Actual[INPUTS];
	UWORD LogIn[INPUTS];
	UWORD LogOut[INPUTS];
#endif
#ifndef   DISABLE_OLD_COLOR
	COLORSTRUCT NxtCol[INPUTS];
#endif
	DATA16 OutPin5Low[OUTPUTS]; //!< Analog value at output port connection 5 when connection 6 is low

	DATA8 Updated[INPUTS];

	DATA8 InDcm[INPUTS];          //!< Input port device types
	DATA8 InConn[INPUTS];

	DATA8 OutDcm[OUTPUTS];        //!< Output port device types
	DATA8 OutConn[OUTPUTS];
#ifndef DISABLE_PREEMPTED_VM
UWORD PreemptMilliSeconds;
#endif
} ANALOG;

/*\endverbatim
 *
 *  \n
 */

/*! \page UartModuleMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the uart values for use in userspace
 *  this pointer will point to a struct and the layout is following:
 *
 *  \verbatim
 */

#define   UART_DATA_LENGTH        MAX_DEVICE_DATALENGTH
#define   UART_BUFFER_SIZE        64

typedef struct {
TYPES TypeData[INPUTS][MAX_DEVICE_MODES]; //!< TypeData

#ifndef DISABLE_FAST_DATALOG_BUFFER
UWORD Repeat[INPUTS][DEVICE_LOGBUF_SIZE];
DATA8 Raw[INPUTS][DEVICE_LOGBUF_SIZE][UART_DATA_LENGTH]; //!< Raw value from UART device
UWORD Actual[INPUTS];
UWORD LogIn[INPUTS];
#else
DATA8 Raw[INPUTS][UART_DATA_LENGTH];      //!< Raw value from UART device
#endif
DATA8 Status[INPUTS];                     //!< Status
DATA8 Output[INPUTS][UART_DATA_LENGTH];   //!< Bytes to UART device
DATA8 OutputLength[INPUTS];
} UART;

/*\endverbatim
 *
 *  \n
 */

#define   UART_PORT_CHANGED       0x01        //!< Input port changed#define   UART_DATA_READY         0x08        //!< Data is ready#define   UART_WRITE_REQUEST      0x10        //!< Write request
typedef struct {
DATA8 Connection[INPUTS];
DATA8 Type[INPUTS];
DATA8 Mode[INPUTS];
} DEVCON;

typedef struct {
TYPES TypeData;
DATA8 Port;
DATA8 Mode;
} UARTCTL;

#define   UART_SET_CONN           _IOWR('u',0,DEVCON)
#define   UART_READ_MODE_INFO     _IOWR('u',1,UARTCTL)
#define   UART_NACK_MODE_INFO     _IOWR('u',2,UARTCTL)
#define   UART_CLEAR_CHANGED      _IOWR('u',3,UARTCTL)

/*! \page IicModuleMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the iic values for use in userspace
 *  this pointer will point to a struct and the layout is following:
 *
 *  \verbatim
 */

#define   IIC_DATA_LENGTH         MAX_DEVICE_DATALENGTH
#define   IIC_NAME_LENGTH         8

typedef struct {
TYPES TypeData[INPUTS][MAX_DEVICE_MODES]; //!< TypeData

#ifndef DISABLE_FAST_DATALOG_BUFFER
UWORD Repeat[INPUTS][DEVICE_LOGBUF_SIZE];
DATA8 Raw[INPUTS][DEVICE_LOGBUF_SIZE][IIC_DATA_LENGTH]; //!< Raw value from IIC device
UWORD Actual[INPUTS];
UWORD LogIn[INPUTS];
#else
DATA8 Raw[INPUTS][IIC_DATA_LENGTH];      //!< Raw value from IIC device
#endif
DATA8 Status[INPUTS];                     //!< Status
DATA8 Changed[INPUTS];
DATA8 Output[INPUTS][IIC_DATA_LENGTH];    //!< Bytes to IIC device
DATA8 OutputLength[INPUTS];
} IIC;

/*\endverbatim
 *
 *  \n
 */

#define   IIC_PORT_CHANGED       0x01         //!< Input port changed#define   IIC_DATA_READY         0x08         //!< Data is ready#define   IIC_WRITE_REQUEST      0x10         //!< Write request
typedef struct {
TYPES TypeData;
DATA8 Port;
DATA8 Mode;
} IICCTL;

typedef struct {
RESULT Result;
DATA8 Port;
DATA8 Repeat;
DATA16 Time;
DATA8 WrLng;
DATA8 WrData[IIC_DATA_LENGTH];
DATA8 RdLng;
DATA8 RdData[IIC_DATA_LENGTH];
} IICDAT;

typedef struct {
DATA8 Port;
DATA16 Time;
DATA8 Type;
DATA8 Mode;
DATA8 Manufacturer[IIC_NAME_LENGTH + 1];
DATA8 SensorType[IIC_NAME_LENGTH + 1];
DATA8 SetupLng;
ULONG SetupString;
DATA8 PollLng;
ULONG PollString;
DATA8 ReadLng;
} IICSTR;

#define   IIC_SET_CONN            _IOWR('i',2,DEVCON)
#define   IIC_READ_TYPE_INFO      _IOWR('i',3,IICCTL)
#define   IIC_SETUP               _IOWR('i',5,IICDAT)
#define   IIC_SET                 _IOWR('i',6,IICSTR)

#define   TST_PIN_LENGTH    8

typedef struct {
DATA8 Port;
DATA8 Length;
DATA8 String[TST_PIN_LENGTH + 1];
} TSTPIN;

#define   TST_PIN_ON              _IOWR('t',1,TSTPIN)
#define   TST_PIN_OFF             _IOWR('t',2,TSTPIN)
#define   TST_PIN_READ            _IOWR('t',3,TSTPIN)
#define   TST_PIN_WRITE           _IOWR('t',4,TSTPIN)

#define   TST_UART_LENGTH         UART_BUFFER_SIZE

typedef struct {
DATA32 Bitrate;
DATA8 Port;
DATA8 Length;
DATA8 String[TST_UART_LENGTH];
} TSTUART;

#define   TST_UART_ON             _IOWR('t',5,TSTUART)
#define   TST_UART_OFF            _IOWR('t',6,TSTUART)
#define   TST_UART_EN             _IOWR('t',7,TSTUART)
#define   TST_UART_DIS            _IOWR('t',8,TSTUART)
#define   TST_UART_READ           _IOWR('t',9,TSTUART)
#define   TST_UART_WRITE          _IOWR('t',10,TSTUART)

/*! \page UiModuleMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the ui button states for use in userspace
 *  this pointer will point to a struct and the layout is following:
 *
 *  \verbatim
 */

typedef struct {
DATA8 Pressed[BUTTONS];                   //!< Pressed status
} UI;

/*\endverbatim
 *
 *  \n
 */

#define   LCD_BUFFER_SIZE (((LCD_WIDTH + 7) / 8) * LCD_HEIGHT)
#define   LCD_TOPLINE_SIZE (((LCD_WIDTH + 7) / 8) * (TOPLINE_HEIGHT + 1))

/*! \page DisplayModuleMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the display memory for use in userspace
 *  this pointer will point to a frame buffer as follows:
 *
 *  \verbatim
 */

typedef struct {
UBYTE Lcd[LCD_BUFFER_SIZE];
} LCD;

/*\endverbatim
 *
 *  \n
 */

/*! \page SoundModuleMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the sound ready flag for use in userspace
 *  this pointer will point to a struct and the layout is following:
 *
 *  \verbatim
 */

typedef struct {
DATA8 Status;                       //!< Status
} SOUND;

/*\endverbatim
 *
 *  \n
 */

/*! \page UsbModuleMemory
 *
 *  <b>     Shared Memory </b>
 *
 *  <hr size="1"/>
 *
 *  It is possible to get a pointer to the USB Speed (FULL or HIGH) for use in userspace
 *  this pointer will point to a struct and the layout is following:
 *
 *  \verbatim
 */

enum {
FULL_SPEED, HIGH_SPEED
};

typedef struct {
DATA8 Speed;
} USB_SPEED;

/*\endverbatim
 *
 *  \n
 */

/*! \page VmNonvolatileMemory
 *
 *  <b>     VM non volatile Memory </b>
 *
 *  <hr size="1"/>
 *
 *  This struct will be loaded at start up and save when closing down VM
 *
 *  \verbatim
 */

typedef struct {
DATA8 VolumePercent;                //!< System default volume [0..100%]
DATA8 SleepMinutes;               //!< System sleep          [0..120min] (0 = ~)
} NONVOL;

/*\endverbatim
 *
 *  \n
 */

/*
 *                      Motor/OUTPUT Typedef
 */
typedef struct {
SLONG TachoCounts;
SBYTE Speed;
SLONG TachoSensor;
} MOTORDATA;

typedef struct {
DATA8 Cmd;
DATA8 Nos;
DATA8 Power;
DATA32 Step1;
DATA32 Step2;
DATA32 Step3;
DATA8 Brake;
} STEPPOWER;

typedef struct {
DATA8 Cmd;
DATA8 Nos;
DATA8 Power;
DATA32 Time1;
DATA32 Time2;
DATA32 Time3;
DATA8 Brake;
} TIMEPOWER;

typedef struct {
DATA8 Cmd;
DATA8 Nos;
DATA8 Speed;
DATA32 Step1;
DATA32 Step2;
DATA32 Step3;
DATA8 Brake;
} STEPSPEED;

typedef struct {
DATA8 Cmd;
DATA8 Nos;
DATA8 Speed;
DATA32 Time1;
DATA32 Time2;
DATA32 Time3;
DATA8 Brake;
} TIMESPEED;

typedef struct {
DATA8 Cmd;
DATA8 Nos;
DATA8 Speed;
DATA16 Turn;
DATA32 Step;
DATA8 Brake;
} STEPSYNC;

typedef struct {
DATA8 Cmd;
DATA8 Nos;
DATA8 Speed;
DATA16 Turn;
DATA32 Time;
DATA8 Brake;
} TIMESYNC;
/*
 *                 End of Motor/OUTPUT Typedef
 */

#define     PRINTBUFFERSIZE             160

typedef struct {
NONVOL NonVol;
DATA8 FirstProgram[MAX_FILENAME_SIZE];

char PrintBuffer[PRINTBUFFERSIZE + 1];
DATA8 TerminalEnabled;

PRGID FavouritePrg;
PRGID ProgramId;                    //!< Program id running
PRG Program[MAX_PROGRAMS];        //!< Program[0] is the UI byte codes running

ULONG InstrCnt;                     //!< Instruction counter (performance test)
IP pImage;                       //!< Pointer to start of image
GP pGlobal;                      //!< Pointer to start of global bytes
OBJHEAD* pObjHead;                     //!< Pointer to start of object headers
OBJ** pObjList;                     //!< Pointer to object pointer list

IP ObjectIp;                     //!< Working object Ip
LP ObjectLocal;                  //!< Working object locals
OBJID Objects;                      //!< No of objects in image
OBJID ObjectId;                     //!< Active object id

IP ObjIpSave;
GP ObjGlobalSave;
LP ObjLocalSave;
DSPSTAT DispatchStatusSave;
ULONG PrioritySave;

long TimerDataSec;
long TimerDatanSec;

UWORD Debug;

UWORD Test;

UWORD RefCount;

ULONG TimeuS;

ULONG OldTime1;
ULONG OldTime2;
ULONG NewTime;
#ifdef ENABLE_PERFORMANCE_TEST
ULONG PerformTimer;
DATAF PerformTime;
#endif

DSPSTAT DispatchStatus;               //!< Dispatch status
ULONG Priority;                     //!< Object priority

ULONG Value;
HANDLER Handle;

ERR Errors[ERROR_BUFFER_SIZE];
UBYTE ErrorIn;
UBYTE ErrorOut;

DATA32 MemorySize;
DATA32 MemoryFree;
ULONG MemoryTimer;

#ifndef DISABLE_SDCARD_SUPPORT
DATA32 SdcardSize;
DATA32 SdcardFree;
ULONG SdcardTimer;
DATA8 SdcardOk;
#endif

#ifndef DISABLE_USBSTICK_SUPPORT
DATA32 UsbstickSize;
DATA32 UsbstickFree;
ULONG UsbstickTimer;
DATA8 UsbstickOk;
#endif

LCD LcdBuffer;                    //!< Copy of last LCD update
DATA8 LcdUpdated;                   //!< LCD updated

ANALOG Analog;
ANALOG *pAnalog;
int AdcFile;

#ifdef ENABLE_STATUS_TEST
DATA8 Status;
#endif

#if       (HARDWARE == SIMULATION)
class NXT * nxt;
#endif
} GLOBALS;

#if       (HARDWARE == SIMULATION)
extern GLOBALS * gInstance;
#define VMInstance (*gInstance)
RESULT mSchedInit();
RESULT mSchedCtrl();
RESULT mSchedExit();

void setInstance(GLOBALS * _Instance);
GLOBALS * getInstance();
#else
extern GLOBALS VMInstance;
#endif

#endif /* LMS2012_H_ */
